package com.ghost.alibabaghost.exception;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 包： com.ghost.alibabaghost.exception
 * 项目名称 alighost
 * @author yaolsa
 * 创建时间 2022/4/2 14:53
 * 描述：应用去全局异常处理
 * Version 1.0
 */
@RestControllerAdvice
public class GhostExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(GhostExceptionHandler.class);

    /**
     * 处理自定义异常
     *
     */
    @ExceptionHandler(value = GhostException.class)
    public ExceptionResult bizExceptionHandler(GhostException e) {
        log.error(e.getMessage(), e);
        return ExceptionResult.defineError(e);
    }

    /**
     *处理其他异常
     *
     */
    @ExceptionHandler(value = Exception.class)
    public ExceptionResult exceptionHandler( Exception e) {
        log.error(e.getMessage(), e);
        return ExceptionResult.otherError(ErrorEnum.INTERNAL_SERVER_ERROR);

    }

    /**
     * 处理 json 请求体调用接口对象参数校验失败抛出的异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ExceptionResult jsonParamsException(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        List<Object> errorList = new ArrayList();
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            String msg = String.format("%s%s；", fieldError.getField(), fieldError.getDefaultMessage());
            errorList.add(msg);
        }
        log.error("参数校验异常---->",e.getMessage());
        return ExceptionResult.validError(ErrorEnum.PARAM_ERROR, errorList);
    }


    /**
     * 处理单个参数校验失败抛出的异常
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public ExceptionResult ParamsException(ConstraintViolationException e) {

        List<Object> errorList = new ArrayList();
        Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
        for (ConstraintViolation<?> violation : violations) {
            StringBuilder message = new StringBuilder();
            Path path = violation.getPropertyPath();
            String[] pathArr = StringUtils.split(path.toString(), ".");
            String msg = message.append(pathArr[1]).append(violation.getMessage()).toString();
            errorList.add(msg);
        }
        log.error("参数校验异常---->",e.getConstraintViolations());
        return ExceptionResult.validError(ErrorEnum.PARAM_ERROR, errorList);
    }

    /**
     * @param e
     * @return 处理 form data方式调用接口对象参数校验失败抛出的异常
     */
    @ExceptionHandler(BindException.class)
    public ExceptionResult formDaraParamsException(BindException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        List<String> collect = fieldErrors.stream()
                .map(o -> o.getField() + o.getDefaultMessage())
                .collect(Collectors.toList());
        log.error("参数校验异常---->",e);
        return ExceptionResult.validError(ErrorEnum.PARAM_ERROR, collect);
    }

    /**
     * 请求方法不被允许异常
     */
  /*  @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ExceptionResult httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        return ExceptionResult.validError(ErrorEnum.INTERNAL_SERVER_ERROR,e);
    }
*/

}
